﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics.Contracts;
using Bamboo.Core;
using NHibernate;

namespace Bamboo.Infrastructure.Repository.NHibernate
{
    /// <summary>
    /// An implementation of Bamboo.Core.IUnitOfWork that wraps NHibernate.ITransaction
    /// </summary>
    public class UnitOfWork : IUnitOfWork
    {
        internal UnitOfWork(ISession session, System.Data.IsolationLevel isolationLevel)
        {
            Contract.Requires(session != null);
            Contract.Ensures(this.transaction != null, "An instance of NHibernate.ITransaction should have been created");

            this.session = session;
            this.transaction = this.session.BeginTransaction(isolationLevel);
        }

        internal UnitOfWork(ISession session)
            : this(session, System.Data.IsolationLevel.ReadCommitted)
        {
        }

        protected readonly ITransaction transaction;
        protected readonly ISession session;

        #region IUnitOfWork Members

        public object Add(object entity)
        {
            return this.session.Save(entity);
        }

        public void Update(object entity)
        {
            this.session.Update(entity);
        }

        public void Remove(object entity)
        {
            this.session.Delete(entity);
        }

        public void AddOrUpdate(object entity)
        {
            this.session.SaveOrUpdate(entity);
        }

        public void Commit()
        {
            this.transaction.Commit();
        }

        public void Rollback()
        {
            this.transaction.Rollback();
        }

        #endregion

        #region IDisposable Members

        private bool disposed = false;

        public void Dispose()
        {
            if (!this.disposed)
            {
                if (this.transaction.IsActive)
                {
                    this.transaction.Rollback();
                }

                this.transaction.Dispose();

                this.disposed = true;
            }            
        }

        #endregion
    }
}
